package appfuse.framework;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

import appfuse.framework.exceptions.BaseException;
import appfuse.framework.util.Trace;
import appfuse.framework.util.IConstants;
/**
 * 一般Action虚类
 * <p>
 * Title:WebvegaBaseAction
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: Copyright (c) 2005
 * </p>
 * <p>
 * Company: appfuse
 * </p>
 * 
 * @author hewei
 * @since 2005-10-31
 */
abstract public class WebvegaBaseAction extends Action {
	Log log = LogFactory.getLog(this.getClass());


	/**
	 * Retrieve a session object based on the request and the attribute name.
	 */
	protected Object getSessionObject(HttpServletRequest req, String attrName) {
		Object sessionObj = null;
		HttpSession session = req.getSession(false);
		if (session != null) {
			sessionObj = session.getAttribute(attrName);
		}
		return sessionObj;
	}

	/**
	 * Retrieve an object from the application scope by its name. This is a
	 * convience method.
	 */
	protected Object getApplicationObject(String attrName) {
		return servlet.getServletContext().getAttribute(attrName);
	}

	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		ActionForward forwardPage = null;
		try {
			Calendar c = Calendar.getInstance();
			c.setTime(new Date());
			long a = c.getTimeInMillis();
			
			// Inform the specific action instance to do its thing
			forwardPage = executeAction(mapping, form, request, response);
			
			c.setTime(new Date());
			long b = c.getTimeInMillis();
			Trace.traceEx("执行action时间:"+(b-a)+"ms");
		} catch (BaseException ex) {
			// Log the application exception using your logging framework
			// Call the generic exception handler routine
			forwardPage = processExceptions(request, mapping, ex);
		} catch (Throwable ex) {
			// Log the system exception using your logging framework
			// Treat all other exceptions as system errors
			ex.printStackTrace();
			forwardPage = mapping.findForward(IConstants.APP_ERROR_PAGE_KEY);
		}
		return forwardPage;
	}

	/**
	 * executeAction
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return
	 * @throws BaseException
	 * @throws ParseException
	 */
	abstract public ActionForward executeAction(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception;

	/**
	 * processExceptions
	 * 
	 * @param request
	 * @param mapping
	 * @param ex
	 * @return
	 */
	protected ActionForward processExceptions(HttpServletRequest request,
			ActionMapping mapping, BaseException ex) {
		ActionMessages errors = new ActionMessages();
		ActionForward forward = null;

		Locale locale = getLocale(request);

		processBaseException(errors, ex, locale);

		String inputStr = mapping.getInput();
		ActionForward failureForward = mapping
				.findForward(IConstants.APP_ERROR_PAGE_KEY);

		if (inputStr != null) {
			forward = new ActionForward(inputStr);
		} else if (failureForward != null) {
			forward = failureForward;
		}

		List exceptions = ex.getExceptions();
		if (exceptions != null && !exceptions.isEmpty()) {
			Iterator iter = exceptions.iterator();

			while (iter.hasNext()) {
				BaseException subException = (BaseException) iter.next();
				processBaseException(errors, subException, locale);
			}

			saveMessages(request, errors);
		}
		return forward;
	}

	/**
	 * processBaseException
	 * 
	 * @param errors
	 * @param ex
	 * @param locale
	 */
	protected void processBaseException(ActionMessages errors,
			BaseException ex, Locale locale) {

		// Holds the reference to the ActionError to be added
		// ActionError newActionError = null;
		ActionMessage newActionError = null;

		// The errorCode is the key to the resource bundle
		String errorCode = ex.getMessageKey();
		/**
		 * If there are extra arguments to be used by the MessageFormat object,
		 * insert them into the argList. The arguments are context sensitive
		 * arguments for the exception; there may be 0 or more.
		 */
		Object[] args = ex.getMessageArgs();

		/**
		 * In an application that had to support I18N, you might want to format
		 * each value in the argument array based on its type and the user
		 * locale. For example, if there is a Date object in the array, it would
		 * need to be formatted for each locale.
		 */

		// Now construct an instance of the ActionError class
		if (args != null && args.length > 0) {
			// Use the arguments that were provided in the exception
			newActionError = new ActionMessage(errorCode, args);
		} else {
			newActionError = new ActionMessage(errorCode);
		}
		errors.add(ActionMessages.GLOBAL_MESSAGE, newActionError);
	}
}
